{--------------------------------------------------------------------------- (c) Copyright Aleksandrov O.E., 1999 Molecular Physics department, USTU, Ekaterinsburg, K-2, 620002, RUSSIA phone 75-47-15 E-mail: aleks@dpt.ustu.ru (c) Copyright Александров О.Е., 1999 620002, Екатеринбург, К-2, УГТУ, Кафедра молекулярной физики тел. 75-47-15 E-mail: aleks@dpt.ustu.ru ----------------------------------------------------------------------------} {$O+,F+,N-,S-,Q-} { Delphi 3 compatible } {$IfDef VER70} {$Define Seg16} {$EndIf} Unit xStrings; INTERFACE {$IfDef Seg16} procedure Exchange(var var1,var2; size:word); function Equal(const p1,p2; size:word):boolean; function FindDifference(const p1,p2; size:word):word; {БЫСТРОЕ заполнение участка памяти шаблоном} procedure FillMemByPattern(var Memory; Size:word; const Pattern; PatternSize:word); procedure FillMemByByte(var Memory; Size:word; b:Byte); procedure FillMemByWord(var Memory; Size:word; w:Word); {$Else IfDef Seg16} procedure Exchange(var var1,var2; size:cardinal); register; function Equal(const p1,p2; size:cardinal):boolean; function FindDifference(const p1,p2; size:cardinal):cardinal; {БЫСТРОЕ заполнение участка памяти шаблоном} procedure FillMemByPattern(var Memory; Size:cardinal; const Pattern; PatternSize:cardinal); procedure FillMemByByte(var Memory; Size:cardinal; b:Byte); procedure FillMemByWord(var Memory; Size:cardinal; w:Word); {$EndIf Def Seg16} procedure Move(var src,dst; size:word); {$IfDef DELPHI} register{$EndIf } procedure xxMove; procedure MoveStr(src:string; var dst:string); procedure MoveDiff(var src,dst; size:word); function BytesSum(var area; size:word):longint; 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; procedure FillByteArray(var ByteArray:array of byte; b:Byte); procedure FillWordArray(var WordArray:array of word; w:word); IMPLEMENTATION procedure FillByteArray(var ByteArray:array of byte; b:Byte); begin FillMemByByte(ByteArray, Succ(High(ByteArray)), b); end; procedure FillWordArray(var WordArray:array of word; w:word); begin FillMemByWord(WordArray, Succ(High(WordArray)), w); end; procedure FillMemByByte; assembler; {$IfNDef Delphi} asm mov cx,Size; jcxz @End les di,Memory; mov al,b cld shr cx,1; jnc @FillW stosb jcxz @End @FillW: mov ah,al rep stosw @End: end; {$Else IfNDef Delphi} register; { EAX->Memory; EDX:=Size; ECX=b) } asm xchg Size,ECX {mov ecx,Size;} jcxz @Skip push edi mov edi,Memory; mov al,dl shr cx,1; jnc @FillW stosb jcxz @End @FillW: shr cx,1; jnc @FillDW mov ah,al stosw jcxz @End @FillDW: mov ah,al; mov dx,ax; shl eax,16; mov ax,dx rep stosd @End: pop edi @Skip: end; {$EndIf NDef Delphi} procedure FillMemByWord; assembler; {$IfNDef Delphi} asm mov cx,Size; jcxz @End les di,Memory; mov ax,w cld rep stosw @End: end; {$Else IfNDef Delphi} asm {mov ecx,Size;} jcxz @Skip push edi mov edi,Memory; mov ax,w; shr cx,1; jnc @FillDW stosw jcxz @End @FillDW: mov dx,ax; shl eax,16; mov ax,dx rep stosd @End: pop edi @Skip: end; {$EndIf NDef Delphi} procedure FillMemByPattern; assembler; {$IfNDef Delphi} asm push ds mov ax,Size mov dx,PatternSize; mov cx,dx cmp ax,cx; jae @Cont mov cx,ax @Cont: jcxz @Done les di,Memory; mov bx,di lds si,Pattern cld {копирование 1 Pattern в Memory} shr cx,1 jnc @FillWords movsb; jcxz @Skip @FillWords: rep movsw @Skip: {копирование остального} mov cx,ax; sub cx,dx; jbe @Done mov si,bx; mov dx,es; mov ds,dx shr cx,1 jnc @AFillWords movsb; jcxz @ASkip @AFillWords: rep movsw @ASkip: @Done: pop ds end; (*asm push ds les di,Memory; mov ax,Size; lds bx,Pattern; mov dx,PatternSize; cld @Loop: sub ax,dx; jc @EndLoop call @SubMove jmp @Loop { begin -- локальная подпрограмма --} @SubMove: mov si,bx; mov cx,dx; shr cx,1 jnc @FillWords movsb @FillWords: rep movsw retn { end -- локальная подпрограмма --} @EndLoop: add ax,dx; mov dx,ax; call @SubMove pop ds end;*) {$Else IfNDef Delphi} asm push ebx; push esi; push edi mov edi,Memory; mov eax,Size; mov esi,Pattern; mov edx,PatternSize; mov ecx,edx cmp eax,ecx; jae @Cont mov ecx,eax @Cont: jecxz @Done mov ebx,edi {копирование 1 Pattern в Memory} shr cx,1 jnc @FillWords movsb; jcxz @Skip @FillWords: rep movsw @Skip: {копирование остального} mov ecx,eax; sub ecx,edx; jbe @Done mov esi,ebx shr cx,1 jnc @AFillWords movsb; jcxz @ASkip @AFillWords: rep movsw @ASkip: @Done: pop edi; pop esi; pop ebx end; (*asm push ebx; push esi; push edi mov edi,Memory; mov eax,Size; mov ebx,Pattern; mov edx,PatternSize; @Loop: sub eax,edx; jc @EndLoop call @SubMove jmp @Loop { begin -- локальная подпрограмма --} @SubMove: mov esi,ebx; mov ecx,edx; shr ecx,1 jnc @FillWords movsb @FillWords: rep movsw retn { end -- локальная подпрограмма --} @EndLoop: add eax,edx; mov edx,eax; call @SubMove pop edi; pop esi; pop ebx end;*) {$EndIf NDef Delphi} {-----------------------------------------------------------------------------} { 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: jecxz @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(var src,dst; size:word); 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} {$IfDef Seg16} function Equal(const p1,p2; size:word):boolean; { 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. } assembler; asm mov dx,ds { Сохранение DS } mov cx,size; jcxz @OK 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: jcxz @OK repe cmpsw jne @END @OK: mov al,TRUE { AL:=TRUE } @End: mov ds,dx { Восстановление DS } end; {$Else Seg16} function Equal(const p1,p2; size:cardinal):boolean; { 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. } assembler; asm push ebx; push esi; push edi mov ecx,size jecxz @OK mov edi,p1 mov esi,p2 xor eax,eax 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: jecxz @OK repe cmpsd jne @END @OK: mov eax,TRUE { AL:=TRUE } @End: pop edi; pop esi; pop ebx end; {$EndIf Def Seg16} {$IfDef Seg16} function FindDifference(const p1,p2; size:word):word; assembler; asm mov dx,ds { Сохранение DS } mov cx,size; les di,p1; lds si,p2 cld mov ax,cx repe cmpsb je @OK sub ax,cx; inc ax jmp @End @OK: xor ax,ax @End: mov ds,dx { Восстановление DS } end; {$Else Seg16} function FindDifference(const p1,p2; size:cardinal):cardinal; assembler; asm push ebx; push esi; push edi mov ecx,size; mov edi,p1 mov esi,p2 mov eax,ecx; 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.