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