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

Unit MEM16;
{
 Author:        Paul VanderSpek
 Date:          03-20-1993

    This source code is being released as Free-Ware.  You may use
  this code in your Programs and modify it to fit your needs. The
  only  restrictions are that you  may not distribute the  source
  code in modified Form or Charge For the source code itself.


}

Interface

Procedure Move16(Var Source,Dest;Count:Word);
Procedure FillChar16(Var X; Count: Word; Value:Byte);

Implementation

Procedure Move16(Var Source,Dest;Count:Word); Assembler;
Asm
  PUSH DS
  LDS SI,SOURCE
  LES DI,DEST
  MOV AX,COUNT
  MOV CX,AX
  SHR CX,1
  REP MOVSW
  TEST AX,1
  JZ @end
  MOVSB
@end:POP DS
end;

Procedure FillChar16(Var X; Count: Word; Value:Byte); Assembler;
Asm
  LES DI,X
  MOV CX,COUNT
  SHR CX,1
  MOV AL,ValUE
  MOV AH,AL
  REP StoSW
  TEST COUNT,1
  JZ @end
  StoSB
@end:
end;

end.

{
These routines are twice as fast as the normal Move and FillChar routines
sInce they use MOVSW and StoSW instead of MOVSB and StoSB. They work in
exactly the same way, so you can just replace Move and FillChar With them.
}

{
>     This source code is being released as Free-Ware.  You may use
>   this code in your Programs and modify it to fit your needs. The
>   only  restrictions are that you  may not distribute the  source
>   code in modified form or Charge For the source code itself.

I'm sorry to say that I'm not impressed, since hundreds of people already have
invented this wheel.  Besides, your move routine has at least one serious flaw:
it assumes that source and destinaton do not overlap.  Which is not always the
case; if you have a Variable of the Type String as the source, and you want to
copy a few Characters furtheron in this Variable, you'll mess up the result.

>      SHR CX,1
>      REP MOVSW
>      TEST AX,1
>      JZ @end
>      MOVSB
> @end:POP DS

The TEST AX, 1 instruction is superfluous.  If the number of Bytes in the CX
register is odd, the SHR CX, 1 instruction will set the carry bit.  It's more
convenient to test this bit.  Here's how:

         SHR   CX, 1
         JNC   @1
         MOVSB
         REP   MOVSW
    @1:

> Have Fun,

No fun if source and destination overlap, as said earlier.  Here follows a
memory move routine With 16-bit moves and overlap check:
}
Procedure MoveMem(Var source, target; size : Word); Assembler;

Asm
        PUSH    DS
        LDS     SI, source
        LES     DI, target
        MOV     CX, size
        CLD

    { If an overlap of source and target could occur,
      copy data backwards }

        CMP     SI, DI
        JAE     @2

        ADD     SI, CX
        ADD     DI, CX
        DEC     SI
        DEC     DI
        STD

        SHR     CX, 1
        JAE     @1
        MOVSB
@1:     DEC     SI
        DEC     DI
        JMP     @3

@2:     SHR     CX, 1
        JNC     @3
        MOVSB

@3:     REP     MOVSW
        POP     DS
end;  { MoveMem }


{
> For I := 0 to 200 do
>  Move(Buffer,Mem[$A000:0000],320);

Looks weird to me. Why moving all that stuff 200 times to the first line
of the screen ?

> For I := 100 to 200 do
>  Move(Buffer[320*I],Mem[$A000:(I*320)],320);

This could be done via

Move(Buffer[320*StartLine], Mem[$a000:320*StartLine], 320*NumberOfLines) ;

which should somehow be faster.

Also note that TP's Move Procedure Uses a LODSB instruction, which is
twice as slow as a LODSW instruction on 286+ computers, With big buffers.
So here is a replacement Move proc, which works fine EXCEPT if the two
buffers overlap and destination is at a greater address than source, which
anyway is not the Case here.
}
Procedure FastMove(Var Src, Dst ; Cnt : Word) ;
Assembler ;
Asm
     Mov       DX, DS         { Sauvegarde DS }
     Mov       CX, Cnt
     LDS       SI, Src
     LES       DI, Dst
     ClD                      { A priori, on va du dbut vers la fin }
     ShR       CX, 1          { On va travailler sur des mots }
     Rep       MovSW          { Copie des mots }
     JNC       @Done          { Pas d'octet restant (Cnt pair) ? }
     MovSB                    { Copie dernier octet }
@Done:
     Mov       DS, DX         { Restauration DS }
end ;
{
Well, just a note : this proc works twice faster than TP's Move _only_ if
Src and Dst are Word aligned, which is the Case if :
- they are Variables allocated on the heap,
- they are declared in the stack,
- $a+ is specified,
- you use it as described in your examples of code :-)
}

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