{$O+,F+,N-,S-,Q-} { Delphi 3 compatible } Unit xStrings; INTERFACE procedure Exchange(var var1,var2; size:word);{$IfNDef Seg16}register;{$EndIf} procedure Move(var src,dst; size:word); procedure xxMove; procedure MoveStr(src:string; var dst:string); procedure MoveDiff(var src,dst; size:word); function BytesSum(var area; size:word):longint; function Equal(var p1,p2; size:word):boolean; function FindDifference(var p1,p2; size:word):word; function AscizLength(var beg):word; function AscizLenLim(var beg; uplimit:word):word; function NthStr(var fstr; num:word):string; function CopyToStr(str:Pointer; n:Byte):string; function Asciz2String(str:PChar):string; IMPLEMENTATION {-----------------------------------------------------------------------------} { Exchange - обменивает местами две области памяти } procedure Exchange; assembler; {$IfDef Seg16} asm cld { ;exchange goes upward} mov dx,ds { ;save DS} lds si,var1 { ;get first address} les di,var2 { ;get second address} mov cx,size { ;get number of bytes to exchange} shr cx,1 { ;get word count (low bit -> carry)} jnc @ExchangeWords { ;if no odd byte, enter loop} mov al,es:[di] { ;read odd byte from var2} movsb { ;move a byte from var1 to var2} mov [si-1],al { ;write var2 byte to var1} @ExchangeWords: jcxz @Finis { ;done if only one byte to exchange} mov bx,-2 { ;BX is a handy place to keep -2} @ExchangeWordsLoop: mov ax,es:[di] { ;read a word from var2} movsw { ;do a move from var1 to var2} mov [bx][si],ax { ;write var2 word to var1} loop @ExchangeWordsLoop { ;repeat "count div 2" times} @Finis: mov ds,dx { ;get back Turbo's DS} end; {$Else IfDef Seg16} asm push ebx; push esi; push edi mov esi,var1 { ;get first address} mov edi,var2 { ;get second address} // mov cx,size { ;get number of bytes to exchange } shr ecx,1 { ;get word count (low bit -> carry)} jnc @ExchangeWord { ;if no odd byte, enter loop} mov al,[edi] { ;read odd byte from var2} movsb { ;move a byte from var1 to var2} mov [esi-1],al { ;write var2 byte to var1} @ExchangeWord: shr ecx,1 { ;get Dword count (low bit -> carry)} jnc @ExchangeDWords { ;if no odd word, enter loop} mov ax,[edi] { ;read odd byte from var2} movsw { ;move a byte from var1 to var2} mov [esi-2],ax { ;write var2 word to var1} @ExchangeDWords: jcxz @Finis { ;done if less than one dword to exchange} mov ebx,-4 { ;BX is a handy place to keep -4} @ExchangeDWordsLoop: mov eax,[edi] { ;read a word from var2} movsd { ;do a move from var1 to var2} mov [ebx][esi],eax { ;write var2 dword to var1} loop @ExchangeDWordsLoop { ;repeat "count div 2" times} @Finis: pop edi; pop esi; pop ebx end; {$EndIf Def Seg16} procedure xxMove; { DX:SI -> source; ES:DI -> dest; CX:=count of bytes } assembler; {$IfDef Seg16} asm jcxz @End cmp Test8086,2 mov ax,ds; mov ds,dx; cld jae @cpu386 cmp si,di jae @Forward std dec cx; add si,cx; add di,cx; inc cx; movsb @Forward: shr cx,1 { CX:=CX div 2; CF:=CX mod 2 } jnc @MWrds movsb @MWrds: rep movsw jmp @Exit @cpu386: cmp si,di jae @Forward3 std dec cx; add si,cx; add di,cx; inc cx shr cx,1 { CX:=CX div 2; CF:=CX mod 2 } jnc @NoByte3 movsb @NoByte3: dec si; dec di shr cx,1; jnc @NoWord3 movsw @NoWord3: sub si,2; sub di,2 jmp @MDW3 @Forward3: shr cx,1 { CX:=CX div 2; CF:=CX mod 2 } jnc @MW3 movsb @MW3: shr cx,1; jnc @MDW3 movsw @MDW3: jcxz @SkipMDW3 db $F3, $66, $A5 {rep movsd} @SkipMDW3: @Exit: cld mov ds,ax @End: end; {$Else IfDef Seg16} { ESI -> source; EDI -> dest; ECX:=count of bytes } asm jcxz @Skip cmp esi,edi jae @Forward3 std dec ecx; add esi,ecx; add edi,ecx; inc ecx shr cx,1 { CX:=CX div 2; CF:=CX mod 2 } jnc @NoByte3 movsb @NoByte3: dec esi; dec edi shr ecx,1; jnc @NoWord3 movsw @NoWord3: sub esi,2; sub edi,2 jmp @MDW3 @Forward3: cld shr ecx,1 { CX:=CX div 2; CF:=CX mod 2 } jnc @MW3 movsb @MW3: shr ecx,1; jnc @MDW3 movsw @MDW3: jecxz @SkipMDW3 rep movsd @SkipMDW3: @Skip: end; {$EndIf Def Seg16} procedure Move; assembler; {$IfDef Seg16} asm mov cx,size; les si,src; mov dx,es; les di,dst; push cs call near(xxMove) end; {$Else Seg16} asm push ebx; push esi; push edi xor ecx,ecx; mov cx,size; mov esi,src; mov edi,dst; call xxMove cld pop edi; pop esi; pop ebx end; {$EndIf Def Seg16} procedure MoveStr; assembler; {$IfDef Seg16} asm les si,src; mov cl,es:[si]; xor ch,ch; inc cx; mov dx,es; les di,dst push cs call near(xxMove) end; {$Else Seg16} asm push ebx; push esi; push edi mov esi,src; mov cl,[esi]; xor ch,ch; inc cx; mov edi,dst call xxMove cld pop edi; pop esi; pop ebx end; {$EndIf Def Seg16} procedure MoveDiff; assembler; {$IfDef Seg16} asm mov dx,ds { Сохранение DS } mov cx,size; lds si,src les di,dst cld shr cx,1 { CX:=CX div 2 } jnc @NoM movsb @NoM: rep movsw mov ds,dx { Восстановление DS } end; {$Else Seg16} asm push ebx; push esi; push edi xor ecx,ecx; mov cx,size; mov esi,src mov edi,dst cld shr ecx,1 { CX:=CX div 2 } jnc @NoMB movsb @NoMB: shr ecx,1 { CX:=CX div 2 } jnc @NoMW movsw @NoMW: rep movsd pop edi; pop esi; pop ebx end; {$EndIf Def Seg16} function BytesSum(var area; size:word):longint; assembler; {$IfDef Seg16} asm xor ax,ax; xor dx,dx mov cx,size; jcxz @End mov di,ds; lds si,area; xor bx,bx cld @loop: lodsb; add bx,ax; adc dx,0 loop @loop mov ax,bx mov ds,di @End: end; {$Else Seg16} asm xor eax,eax xor ecx,ecx; mov cx,size; jecxz @End push ebx; push esi mov esi,area; xor ebx,ebx cld @loop: lodsb; add ebx,eax loop @loop mov eax,ebx pop esi; pop ebx @End: end; {$EndIf Def Seg16} function Equal(var p1,p2; size:word):boolean; assembler; { Check the equivalence of two memory areas P1 -> first area; P2 -> second area; SIZE:= size of areas to compare; Return: TRUE - if equal, FALSE - if not equal. } {$IfDef Seg16} asm mov dx,ds { Сохранение DS } mov cx,size; les di,p1; lds si,p2 xor al,al cld shr cx,1 { CX:=CX div 2; CF:=CX mod 2 } jnc @CmpWords cmpsb; jne @END @CmpWords: repe cmpsw jne @END mov al,TRUE { AL:=TRUE } @End: mov ds,dx { Восстановление DS } end; {$Else Seg16} asm push ebx; push esi; push edi xor ecx,ecx; mov cx,size; mov edi,p1; mov esi,p2 xor eax,eax cld shr cx,1 { CX:=CX div 2; CF:=CX mod 2 } jnc @CmpWords cmpsb; jne @END @CmpWords: shr cx,1 { CX:=CX div 2; CF:=CX mod 2 } jnc @CmpDWords cmpsw; jne @END @CmpDWords: repe cmpsd jne @END mov eax,TRUE { AL:=TRUE } @End: pop edi; pop esi; pop ebx end; {$EndIf Def Seg16} function FindDifference(var p1,p2; size:word):word; assembler; {$IfDef Seg16} asm mov dx,ds { Сохранение DS } mov cx,size; mov ax,cx; les di,p1; lds si,p2 cld repe cmpsb xchg ax,cx je @END xchg ax,cx; sub ax,cx; inc ax @End: mov ds,dx { Восстановление DS } end; {$Else Seg16} asm push ebx; push esi; push edi xor ecx,ecx; mov cx,size; mov eax,ecx; mov edi,p1; mov esi,p2 cld repe cmpsb xchg eax,ecx je @END xchg eax,ecx; sub eax,ecx; inc eax @End: pop edi; pop esi; pop ebx end; {$EndIf Def Seg16} function AscizLen:word; near; assembler; {$IfDef Seg16} asm mov bx,cx cld xor al,al; repne scasb xchg ax,bx; sub ax,cx dec ax end; {$Else Seg16} asm mov ebx,ecx cld xor al,al; repne scasb xchg eax,ebx; sub eax,ecx dec eax end; {$EndIf Def Seg16} function AscizLength; assembler; {$IfDef Seg16} asm les di,beg { Load addres to ES:[DI] } mov cx,$FFFF call AscizLen end; {$Else Seg16} asm push ebx; push edi mov edi,beg { Load addres to EDI } mov ecx,$FFFFFFFF call AscizLen pop edi; pop ebx end; {$EndIf Def Seg16} function AscizLenLim; assembler; {$IfDef Seg16} asm les di,beg { Load addres to ES:[DI] } mov cx,uplimit call AscizLen end; {$Else Seg16} asm push ebx; push edi mov edi,beg { Load addres to ES:[DI] } xor ecx,ecx; mov cx,uplimit call AscizLen pop edi; pop ebx end; {$EndIf Def Seg16} {---------------------------------------------------------------------------} function NthStr(var fstr; num:word):string; assembler; {$IfDef Seg16} asm mov cx,num cld; les si,fstr; xor ah,ah; jcxz @First @Loop: SEGES lodsb; add si,ax loop @Loop @First: push es; push si les di,@Result; push es; push di {$IFOPT P+} {$IFOPT G+} push $ff {$ELSE} mov ax,$FF; push ax {$ENDIF} {$ENDIF} call MoveStr end; {$Else Seg16} asm push ebx; push esi; push edi xor ecx,ecx; mov cx,num cld; mov esi,fstr; xor eax,eax; jecxz @First @Loop: lodsb; add esi,eax loop @Loop @First: mov edi,@Result xor ecx,ecx; mov cl,[esi] call xxMove pop edi; pop esi; pop ebx end; {$EndIf Def Seg16} function CopyToStr; assembler; {$IfDef Seg16} asm cld les di,@Result mov al,n stosb xor ah,ah; xchg ax,cx; jcxz @Exit mov dx,ds lds si,str shr cx,1 { CX:=CX div 2 } jnc @NoM movsb @NoM: rep movsw mov ds,dx @Exit: end; {$Else Seg16} asm push ebx; push esi; push edi mov esi,str mov edi,@Result xor ecx,ecx mov cl,n call xxMove cld pop edi; pop esi; pop ebx end; {$EndIf Def Seg16} function Asciz2String(str:PChar):string; assembler; {$IfDef Seg16} asm les di,str { Load addres to ES:[DI] } mov cx,255 call AscizLen cld les di,@Result stosb xor ah,ah; xchg ax,cx; jcxz @Exit mov dx,ds lds si,str shr cx,1 { CX:=CX div 2 } jnc @NoM movsb @NoM: rep movsw mov ds,dx @Exit: end; {$Else Seg16} asm push ebx; push esi; push edi mov esi,str mov edi,str { Load addres to EDI } mov ecx,255 call AscizLen mov edi,@Result call xxMove pop edi; pop esi; pop ebx end; {$EndIf Def Seg16} END.