Metropoli BBS
VIEWER: lst11-7.asm MODE: TEXT (ASCII)
;
; *** Listing 11-7 ***
;
; Copies overlapping blocks of memory with MOVS.
; To the greatest possible extent, the copy is
; performed a word at a time.
;
	jmp	Skip
;
TEST_LENGTH1	equ	501	;sample copy length #1
TEST_LENGTH2	equ	1499	;sample copy length #2
TestArray	db	1500 dup (0)
;
; Copies a block of memory CX bytes in length. A value
; of 0 means "copy zero bytes," since it wouldn't make
; much sense to copy one 64K block to another 64K block
; in the same segment, so the maximum length that can
; be copied is 64K-1 bytes and the minimum length
; is 0 bytes. Note that both blocks must be in DS. Note
; also that overlap handling is not guaranteed if either
; block wraps at the end of the segment.
;
; Input:
;	CX = number of bytes to clear
;	DS:SI = start of block to copy
;	DS:DI = start of destination block
;
; Output:
;	none
;
; Registers altered: CX, DX, SI, DI, ES
;
; Direction flag cleared
;
BlockCopyWithOverlap:
	mov	dx,ds	;source and destination are in the
	mov	es,dx	; same segment
	cmp	si,di	;which way do the blocks overlap, if
			; they do overlap?
	jae	LowToHigh
			;source is not below destination, so
			; we can copy from low to high

			;source is below destination, so we
			; must copy from high to low
	add	si,cx	;point to the end of the source
	dec	si	; block
	add	di,cx	;point to the end of the destination
	dec	di	; block
	std		;copy from high addresses to low
	shr	cx,1	;divide by 2, copying the odd-byte
			; status to the Carry flag
	jnc	CopyWordHighToLow ;no odd byte to copy
	movsb		;copy the odd byte
CopyWordHighToLow:
	dec	si	;point one word lower in memory, not
	dec	di	; one byte
	rep	movsw	;move the rest of the block
	cld
	ret
;
LowToHigh:
	cld		;copy from low addresses to high
	shr	cx,1	;divide by 2, copying the odd-byte
			; status to the Carry flag
	jnc	CopyWordLowToHigh	;no odd byte to copy
	movsb		;copy the odd byte
CopyWordLowToHigh:
	rep	movsw	;move the rest of the block
	ret
;
Skip:
	call	ZTimerOn
;
; First run the case where the destination overlaps & is
; higher in memory.
;
	mov	si,offset TestArray
	mov	di,offset TestArray+1
	mov	cx,TEST_LENGTH1
	call	BlockCopyWithOverlap
;
; Now run the case where the destination overlaps & is
; lower in memory.
;
	mov	si,offset TestArray+1
	mov	di,offset TestArray
	mov	cx,TEST_LENGTH2
	call	BlockCopyWithOverlap
	call	ZTimerOff

[ RETURN TO DIRECTORY ]