DataMuseum.dk

Presents historical artifacts from the history of:

CP/M

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦ed20c44cd⟧ TextFile

    Length: 4480 (0x1180)
    Types: TextFile
    Names: »NDIM.MAC«

Derivation

└─⟦01b5c9619⟧ Bits:30005906 Microsoft Multiplan v1.05 og HELP
    └─ ⟦this⟧ »NDIM.MAC« 

TextFile

;
;
;	Title		N-dimensional array indexing
;	Name:		NDIM
;
;
;	Purpose:	Calculate the address of an element in an
;			N-dimensional array given the base address,
;			N pairs of size in bytes and subscript, and the
;			number of dimensions of the array. The array is
;			assumed to be stored in roq major order
;			(AÆ0,0,0Å,AÆ0,0,1Å,...,AÆ0,1,0Å,AÆ0,1,1Å,...).
;			Also it is assumed that all dimensions begin
;			at 0 as in the following Pascal declaration:
;			  A:ARRAYÆ0..10,0..3,0..5Å of something
;			For arrays that do not begin at 0 boundaries,
;			normalization must be performed before calling
;			this routine.
;
;	Entry:		Top of stack
;			  Return address	word
;			  Number dimensions	word
;			  Dim N-1 size		word
;			  Dim N-1 subscript	word
;			  Dim N-2 size		word
;			  Dim N-2 subscript	word
;				.		  .
;				.		  .
;				.		  .
;			  Dim 0 size		word
;			  Dim 0 subscript	word
;			  Array base address	word
;			NOTE:
;			  All sizes are in bytes
;
;	Exit:		HL = address
;
;	Registers used:	AF,BC,DE,HL
;
;	Time:		Approximately 1300 cycles per dimension
;			plus 165 cycles overhead
;
;	Size:		Program 120 bytes
;			Data	  5 bytes
;
;
;
NDIM:
	;pop parameters
	pop	hl		;Return address
	ld	(retadr),hl

	;ofset := 0
	ld	hl,0
	ld	(offset),hl

	;Get number of dimensions and test for 0
	pop	hl
	ld	a,l
	ld	(numdim),a	;Get number of dimensions
	or	a		;Test for 0
	jr	z,adbase	;Return with base in HL
				;  if there are no dimensions

	;Loop each dimension
	;  doing offset := offset + (subscript * size)
loop:
	pop	de		;Get size
	pop	hl		;Get subscript
	call	nxtoff		;Offset := ofset + (subscript * size)
	ld	hl,numdim
	dec	(hl)		;Decrement number of dimensions
	jr	nz,loop		;Continue through all dimensions

adbase:
	;Calculate starting address of element
	;Offset = base + offset
	ld	hl,(offset)
	pop	de		;Get base address
	add	hl,de		;Sum with offset

	;Restore return address and exit
	ld	de,(retadr)
	push	de
	ret

	;--------------------------------------------------
	;Subroutine NXTOFF
	;Purpose: offset := offset + (subscript * size);
	;Entry:	offset = current offset
	;	DE = current size of this dimension
	;	HL = current subscript
	;Exit:	offset = offset + (subscript * size);
	;Registers used:  AF, BC, DE, HL
	;--------------------------------------------------
NXTOFF:
	push	hl		;Save current subscript in stack

	;Check if size is power of 2 less then 256
	ld	a,d
	or	a		;High byte = 0 ?
	jr	nz,bigsz	;Jump if size is large

	ld	a,e		;A =  low byte of size
	ld	hl,easyay	;HL = base address of easyay
	ld	b,szeasy	;B =  size of easy array
	ld	c,0		;C =  shift counter
easylp:
	cp	(hl)
	jr	z,iseasy	;Jump if size is a power of 2
	inc	hl		;Increment to next byte of easay
	inc	c		;Increment shift counter
	djnz	easylp		;Decrement count
	jr	bigsz		;jump if size not easy

iseasy:
	pop	hl		;Get subscript
	ld	a,c		;Get number of shifts
	or	a		;Test for 0
	jr	z,addoff	;Jump if shift factor = 0

	;Element size * subscript reduces to left shifts
	ld	b,a		;B = shift count
shift:
	add	hl,hl		;Multiply subscript by 2
	djnz	shift		;Continue until done
	jr	addoff		;Done so add offset + subscript

bigsz:
	;Size is not power of 2, multiply
	;  element size times subscript the hard way
	pop	bc		;Get subscript

	;Multiply first subscript * row lenght using shift and add
	;  algorihm. Result is in HL
	;  BC = subscript (multiplicand)
	;  DE = size (multiplier)
	ld	hl,0		;Product = 0
	ld	a,15		;count = bit elnght -1
mlp:
	sla	e		;shift low byte of multiplier
	rl	d		;Rotate high byte of multiplier
	jr	nc,mlp1		;Jump if msb of multiplier = 0
	add	hl,bc		;Add multiplicand to partical product
mlp1:	add	hl,hl		;shift partical product
	dec	a
	jr	nz,mlp		;Continue through 15 bits
	;Add in multiplicand last time if msb of multiplier is 1
	or	d		;Sign flag = msb of multiplier
	jp	p,addoff
	add	hl,bc		;Add in multiplicand if sign = 1

	;Add subscript * size to offset
addoff:
	ex	de,hl
	ld	hl,(offset)	;Get offset
	add	hl,de		;Add product of subscript * size
	ld	(offset),hl	;Save offset
	ret

easyay:				;Shift factor
	db	1		;0
	db	2		;1
	db	4		;2
	db	8		;3
	db	16		;4
	db	32		;5
	db	64		;6
	db	128		;7
szeasy	equ	$-easyay

	;DATA
retadr:	ds	2		;Temporary for return address
offset:	ds	2		;Temporary for partial offset
numdim:	ds	1		;Number of dimensions

«eof»