This is a cross-referenced version of move.plan, to download the unmodified source try move.plan.
#PROGRAM       /GFMOVE(15AM,22AM,DBM,EBM)
#PAGE

#INCLUDE       STACK(/DEFS)


#              Move words, coping with overlapping source
#              and dest.

#              void gfmove (int *from, int *to, int words)

#SET           ARGS=0

#DEFINE        ARGFROM=ARGS
#SET           ARGS=ARGS+1

#DEFINE        ARGTO=ARGS
#SET           ARGS=ARGS+1

#DEFINE        ARGWORDS=ARGS
#SET           ARGS=ARGS+1

#              Define stack frame

#SET           STFRAME=SXFRAME

#              First arguments:

#DEFINE        STFROM=SXPAR1
#SET           STFRAME=STFRAME+1

#DEFINE        STTO=SXPAR2
#SET           STFRAME=STFRAME+1

#DEFINE        STWORDS=SXPAR3
#SET           STFRAME=STFRAME+1

#PROGRAM

#              First pick up value args

      STACK 2

      OBEY     ARGWORDS(1)          [ get # words to move
      LDX   0  0(3)           
      STO   0  STWORDS(2)

#           Now get call-by-name args

      OBEY     ARGFROM(1)           [ get source address
      ARRAY 3                       [ arg is array or elem
      STACK 2                       [ restore SP
      STO   3  STFROM(2)

      OBEY     ARGTO(1)             [ get destination address
      ARRAY 3                       [ arg is array or elem
      STACK 2                       [ restore SP
      STO   3  STTO(2)

      ADN   1  ARGS

#              Pascal callable entry point

#CUE           GPMOVE

      BEGIN 2  3,1,STFRAME

      LDX   3  STWORDS(2)
      BZE   3  BYE                  [ do nothing if nothing to do

      LDX   4  STFROM(2)
      LDX   5  STTO(2)
      BZE   4  5,BYE                [ move to self is noop

#              MOVE moves from low addresses to high addresses,
#              so if the starting source address ls less than the
#              destination and the last source address is greater
#              than or equal to the destination we will overwrite
#              the source.

      BXGE  4  5,SAFE            [ if source >= dest use MOVE
      LDX   1  4
      ADX   1  3                 [ x1 = word past end of source
      BXGE  5  1,SAFE            [ if dest beyond source use MOVE

#              We have to do the move ourselves, moving backwards
#              in memory.

      STO   3  7                 [ get count to X7, we need X3
      ADX   3  5                 [ point X3 beyond end of dest

BACK  SBN   1  1                 [ point X6 at source
      SBN   3  1                 [ point X5 at dest
      LDX   0  0(1)              [ get word of source
      STO   0  0(3)              [ move to dest
      BCT   7  BACK              [ loop 'till done

      BRN      BYE

#              The "easy" case - use MOVE
    
SAFE  MOVEW 45 3

BYE   END   2  1,0

#END
#FINISH